/*
 *    Copyright (c) 2018-2025, lengleng All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the pig4cloud.com developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: lengleng (wangiegie@gmail.com)
 */
package com.pig4cloud.pigx.order.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pig4cloud.pigx.common.core.constant.SecurityConstants;
import com.pig4cloud.pigx.common.core.constant.enums.OperEnum;
import com.pig4cloud.pigx.common.core.constant.enums.OrderStatusEnum;
import com.pig4cloud.pigx.common.core.constant.enums.PointChangeSourceEnum;
import com.pig4cloud.pigx.common.core.constant.enums.PointChangeStatusEnum;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.order.api.entity.*;
import com.pig4cloud.pigx.order.api.vo.OrderDeliveryVO;
import com.pig4cloud.pigx.order.api.vo.OrderInfoVO;
import com.pig4cloud.pigx.order.api.vo.PointSpuOrderVO;
import com.pig4cloud.pigx.order.mapper.PointSpuOrderMapper;
import com.pig4cloud.pigx.order.service.DeliveryService;
import com.pig4cloud.pigx.order.service.OrderDeliveryService;
import com.pig4cloud.pigx.order.service.PointSpuOrderDetailService;
import com.pig4cloud.pigx.order.service.PointSpuOrderService;
import com.pig4cloud.pigx.shop.user.api.entity.ShopCoupon;
import com.pig4cloud.pigx.shop.user.api.entity.ShopUserPointChangeRecord;
import com.pig4cloud.pigx.shop.user.api.feign.RemoteShopUserPointChangeRecordService;
import com.pig4cloud.pigx.shop.user.api.feign.RemoteShopUserService;
import com.pig4cloud.pigx.shop.user.api.vo.ShopCouponVO;
import com.pig4cloud.pigx.shop.user.api.vo.ShopUserVO;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 积分商城订单
 *
 * @author pigx code generator
 * @date 2023-12-19 09:23:55
 */
@Slf4j
@Service
@AllArgsConstructor
public class PointSpuOrderServiceImpl extends ServiceImpl<PointSpuOrderMapper, PointSpuOrder>
		implements PointSpuOrderService {

	private final RemoteShopUserService remoteShopUserService;

	private final PointSpuOrderDetailService pointSpuOrderDetailService;

	private final RocketMQTemplate rocketMQTemplate;

	private final RemoteShopUserPointChangeRecordService remoteShopUserPointChangeRecordService;

	private final OrderDeliveryService orderDeliveryService;

	private final DeliveryService deliveryService;

	/**
	 * 分页获取订单数据
	 * @param page
	 * @param pointSpuOrder
	 * @return
	 */
	@Override
	public IPage getPage(Page page, PointSpuOrder pointSpuOrder) {
		IPage<PointSpuOrderVO> result = new Page<>();
		LambdaQueryWrapper<PointSpuOrder> lqwPointSpuOrder = new LambdaQueryWrapper<>();
		if (pointSpuOrder.getShopUserId() != null) {
			lqwPointSpuOrder.eq(PointSpuOrder::getShopUserId, pointSpuOrder.getShopUserId());
		}
		if (!StringUtils.isEmpty(pointSpuOrder.getOrderStatus())) {
			lqwPointSpuOrder.eq(PointSpuOrder::getOrderStatus, pointSpuOrder.getOrderStatus());
		}

		lqwPointSpuOrder.orderByDesc(PointSpuOrder::getCreateTime);
		IPage<PointSpuOrder> items = this.page(page, lqwPointSpuOrder);
		if (items.getRecords().size() > 0) {
			List<Long> orderIds = new ArrayList<>();
			result = items.convert(u -> {
				PointSpuOrderVO v = new PointSpuOrderVO();
				BeanUtils.copyProperties(u, v);
				orderIds.add(u.getId());
				return v;
			});

			LambdaQueryWrapper<PointSpuOrderDetail> lqwPointSpuOrderDetail = new LambdaQueryWrapper<>();
			lqwPointSpuOrderDetail.in(PointSpuOrderDetail::getOrderId, orderIds);
			List<PointSpuOrderDetail> pointSpuOrderDetails = pointSpuOrderDetailService.list(lqwPointSpuOrderDetail);

			result.getRecords().forEach(item -> {
				List<PointSpuOrderDetail> details = pointSpuOrderDetails.stream()
						.filter(p -> p.getOrderId().longValue() == item.getId().longValue())
						.collect(Collectors.toList());
				item.setDetails(details);
			});
		}
		return result;
	}

	/**
	 * 根据订单号获取订单详情
	 * @param orderId
	 * @return
	 */
	@Override
	public PointSpuOrderVO getOrderInfoByOrderId(Long orderId) {
		// 订单信息
		PointSpuOrderVO result = new PointSpuOrderVO();
		PointSpuOrder orderInfo = this.getById(orderId);
		BeanUtils.copyProperties(orderInfo, result);

		// 订单详情
		List<PointSpuOrderDetail> details = pointSpuOrderDetailService
				.list(Wrappers.<PointSpuOrderDetail>lambdaQuery().eq(PointSpuOrderDetail::getOrderId, orderId));
		result.setDetails(details);

		// 用户信息
		R<ShopUserVO> shopUser = remoteShopUserService.getShopUserInfoInner(result.getShopUserId(),
				SecurityConstants.FROM_IN);
		result.setShopUser(shopUser.getData());

		return result;
	}

	/**
	 * 创建积分商城订单
	 * @param pointSpuOrderVO
	 * @return
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public R create(PointSpuOrderVO pointSpuOrderVO) {
		Long shopUserId = pointSpuOrderVO.getShopUserId();

		// 获取用户信息
		R<ShopUserVO> shopUserInfoInner = remoteShopUserService.getShopUserInfoInner(shopUserId,
				SecurityConstants.FROM_IN);
		ShopUserVO shopUserVO = shopUserInfoInner.getData();
		if (shopUserVO == null) {
			return R.failed("用户不存在，无法下单");
		}

		// 判断积分是否够
		if (shopUserVO.getShopUserInfo().getPointBalance() < pointSpuOrderVO.getTotalPoint()) {
			return R.failed("积分不足，无法兑换.");
		}

		pointSpuOrderVO.setOrderStatus(OrderStatusEnum.PROCESSED.getType());
		// 创建积分订单
		this.save(pointSpuOrderVO);
		Long orderId = pointSpuOrderVO.getId();

		// 创建积分订单详情
		pointSpuOrderVO.getDetails().forEach(item -> {
			item.setSpuId(item.getId());
			item.setOrderId(orderId);
			item.setId(null);
		});
		pointSpuOrderDetailService.saveBatch(pointSpuOrderVO.getDetails());
		pointOrderSuccessUserPointChange(pointSpuOrderVO);
		return R.ok(pointSpuOrderVO);
	}

	/**
	 * 获取订单详情
	 * @param shopUserId
	 * @param orderId
	 * @return
	 */
	@Override
	public R getOrderInfo(Long shopUserId, Long orderId) {
		PointSpuOrderVO result = new PointSpuOrderVO();

		// 获取订单信息
		PointSpuOrder orderInfo = this.getById(orderId);
		if (orderInfo == null) {
			return R.failed("订单不存在");
		}

		BeanUtils.copyProperties(orderInfo, result);

		// 获取订单商品sku详情
		LambdaQueryWrapper<PointSpuOrderDetail> lqwPointSpuOrderDetail = new LambdaQueryWrapper<>();
		lqwPointSpuOrderDetail.eq(PointSpuOrderDetail::getOrderId, orderId);
		List<PointSpuOrderDetail> pointSpuOrderDetails = pointSpuOrderDetailService.list(lqwPointSpuOrderDetail);
		result.setDetails(pointSpuOrderDetails);

		// 判断订单状态是否是发货
		if (Integer.parseInt(orderInfo.getOrderStatus()) >= Integer.parseInt(OrderStatusEnum.SHIPPED.getType())) {
			result.setOrderDeliveries(new ArrayList<>());
			// 查询物流信息
			LambdaQueryWrapper<OrderDelivery> lqwOrderDelivery = new LambdaQueryWrapper<>();
			lqwOrderDelivery.eq(OrderDelivery::getOrderId, orderId);
			List<OrderDelivery> orderDeliveries = orderDeliveryService.list(lqwOrderDelivery);
			// 获取物流名称
			orderDeliveries.forEach(item -> {
				OrderDeliveryVO orderDeliveryVO = new OrderDeliveryVO();
				BeanUtils.copyProperties(item, orderDeliveryVO);
				Delivery delivery = deliveryService.getById(item.getDeliveryId());
				if (delivery != null) {
					orderDeliveryVO.setDeliveryName(delivery.getDeliveryName());
				}
				result.getOrderDeliveries().add(orderDeliveryVO);
			});
		}

		return R.ok(result);
	}

	/**
	 * 积分订单签收
	 * @param pointSpuOrder
	 * @return
	 */
	@Override
	public R orderSingFor(PointSpuOrder pointSpuOrder) {
		Long orderId = pointSpuOrder.getId();
		Long shopUserId = pointSpuOrder.getShopUserId();

		PointSpuOrder order = this.getOne(Wrappers.<PointSpuOrder>lambdaQuery().eq(PointSpuOrder::getId, orderId)
				.eq(PointSpuOrder::getShopUserId, shopUserId));
		if (order == null) {
			return R.failed("订单不存在");
		}
		PointSpuOrder record = new PointSpuOrder();
		record.setId(orderId);
		// 修改订单状态为待发货
		record.setOrderStatus(OrderStatusEnum.COMPLETE.getType());
		// 设置签收时间
		record.setReceiptTime(LocalDateTime.now());
		// 修改订单信息
		this.updateById(record);

		return R.ok();
	}

	/**
	 * 订单退款
	 * @param pointSpuOrder
	 * @return
	 */
	@Override
	public R orderRefund(PointSpuOrder pointSpuOrder) {
		Long orderId = pointSpuOrder.getId();
		PointSpuOrder spuOrder = this.getById(orderId);
		if (spuOrder == null) {
			return R.failed("订单不存在");
		}

		// 修改订单状态
		PointSpuOrder record = new PointSpuOrder();
		record.setId(orderId);
		// 修改订单状态为已退款
		record.setOrderStatus(OrderStatusEnum.REFUND.getType());
		// 设置退款时间
		record.setRefundTime(LocalDateTime.now());
		// 设置退款理由
		record.setRefundReason(pointSpuOrder.getRefundReason());
		// 修改订单信息
		this.updateById(record);

		// 积分原路返回
		returnUserPoint(spuOrder);

		return R.ok();
	}

	/**
	 * 订单退货
	 * @param pointSpuOrder
	 * @return
	 */
	@Override
	public R orderReturn(PointSpuOrder pointSpuOrder) {
		Long orderId = pointSpuOrder.getId();
		PointSpuOrder spuOrder = this.getById(orderId);
		if (spuOrder == null) {
			return R.failed("订单不存在");
		}

		// 修改订单状态
		PointSpuOrder record = new PointSpuOrder();
		record.setId(orderId);
		// 修改订单状态为已退货
		record.setOrderStatus(OrderStatusEnum.RETURN.getType());
		// 设置退货时间
		record.setReturnTime(LocalDateTime.now());
		// 设置退款理由
		record.setReturnReason(pointSpuOrder.getReturnReason());
		// 修改订单信息
		this.updateById(record);

		// 积分原路返回
		returnUserPoint(spuOrder);

		return R.ok();
	}

	/**
	 * 返回用户积分
	 * @param spuOrder
	 */
	private void returnUserPoint(PointSpuOrder spuOrder) {
		List<PointSpuOrderDetail> pointSpuOrderDetails = pointSpuOrderDetailService.list(
				Wrappers.<PointSpuOrderDetail>lambdaQuery().eq(PointSpuOrderDetail::getOrderId, spuOrder.getId()));
		String pointSpuTitle = "";
		String pointBannerImages = "";
		if (pointSpuOrderDetails.size() > 0) {
			// 默认取第一个sku的信息
			pointSpuTitle = pointSpuOrderDetails.get(0).getSpuTitle();
			pointBannerImages = pointSpuOrderDetails.get(0).getBannerImages();
		}

		// 添加积分上账记录
		ShopUserPointChangeRecord pointChangeRecord = new ShopUserPointChangeRecord();
		pointChangeRecord.setRecordName(pointSpuTitle);
		pointChangeRecord.setRecordImages(pointBannerImages);
		pointChangeRecord.setRecordType(PointChangeSourceEnum.POINT_MALL.getType());
		pointChangeRecord.setShopUserId(spuOrder.getShopUserId());
		pointChangeRecord.setRecordOrderId(spuOrder.getId());
		pointChangeRecord.setStatus(PointChangeStatusEnum.PROCESSING.getType());
		pointChangeRecord.setOper(OperEnum.ADD.getType());
		pointChangeRecord.setPoint(spuOrder.getTotalPoint());
		R result = remoteShopUserPointChangeRecordService.addPointChange(pointChangeRecord, SecurityConstants.FROM_IN);
		if (result.getCode() == 0) {
			Long pointChangeRecordId = Long.parseLong(result.getData().toString());
			pointChangeRecord.setId(pointChangeRecordId);
			log.info("成功添加积分记录，订单号:" + spuOrder.getId() + "，积分抵扣记录ID:" + pointChangeRecordId);

			// 发送积分变更消息
			log.info("发送积分抵扣消息订单号ID:" + spuOrder.getId());
			rocketMQTemplate.convertAndSend("shop-user-point-change", pointChangeRecordId.toString());
			log.info("成功发送积分抵扣消息订单号ID:" + spuOrder.getId());
		}
		else {
			log.info("失败添加积分记录，订单号:" + spuOrder.getId());
		}
	}

	/**
	 * 积分上商城成功兑换后，添加积分
	 * @param pointSpuOrderVO
	 */
	private void pointOrderSuccessUserPointChange(PointSpuOrderVO pointSpuOrderVO) {
		// 获取订单详情
		String pointSpuTitle = "";
		String pointBannerImages = "";
		if (pointSpuOrderVO.getDetails().size() > 0) {
			// 默认取第一个sku的信息
			pointSpuTitle = pointSpuOrderVO.getDetails().get(0).getSpuTitle();
			pointBannerImages = pointSpuOrderVO.getDetails().get(0).getBannerImages();
		}

		// 添加积分上账记录
		ShopUserPointChangeRecord pointChangeRecord = new ShopUserPointChangeRecord();
		pointChangeRecord.setRecordName(pointSpuTitle);
		pointChangeRecord.setRecordImages(pointBannerImages);
		pointChangeRecord.setRecordType(PointChangeSourceEnum.POINT_MALL.getType());
		pointChangeRecord.setShopUserId(pointSpuOrderVO.getShopUserId());
		pointChangeRecord.setRecordOrderId(pointSpuOrderVO.getId());
		pointChangeRecord.setStatus(PointChangeStatusEnum.PROCESSING.getType());
		pointChangeRecord.setOper(OperEnum.SUB.getType());
		pointChangeRecord.setPoint(pointSpuOrderVO.getTotalPoint());
		R result = remoteShopUserPointChangeRecordService.addPointChange(pointChangeRecord, SecurityConstants.FROM_IN);
		if (result.getCode() == 0) {
			Long pointChangeRecordId = Long.parseLong(result.getData().toString());
			pointChangeRecord.setId(pointChangeRecordId);
			log.info("成功添加积分记录，订单号:" + pointSpuOrderVO.getId() + "，积分抵扣记录ID:" + pointChangeRecordId);

			// 发送积分变更消息
			log.info("发送积分抵扣消息订单号ID:" + pointSpuOrderVO.getId());
			rocketMQTemplate.convertAndSend("shop-user-point-change", pointChangeRecordId.toString());
			log.info("成功发送积分抵扣消息订单号ID:" + pointSpuOrderVO.getId());
		}
		else {
			log.info("失败添加积分记录，订单号:" + pointSpuOrderVO.getId());
		}
	}

}
